﻿/*	@file	r_math_matrix43
Copyright (c) 2009 Yuya Yamaguchi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _R_MATH_MATRIX34_H_
#define _R_MATH_MATRIX34_H_

#include "r_math_def.h"

namespace r{
	namespace math{
		struct Vector2D;
		struct Vector3D;
		struct Vector4D;
		struct Matrix33;
		struct Matrix44;


		///
		struct Matrix34 {
		public:
			//! コンストラクタ
			Matrix34 ( void );
			Matrix34 ( r_f32 val );
			Matrix34 (
				r_f32 s11, r_f32 s12, r_f32 s13,
				r_f32 s21, r_f32 s22, r_f32 s23,
				r_f32 s31, r_f32 s32, r_f32 s33,
				r_f32 s41, r_f32 s42, r_f32 s43 );
			Matrix34 ( const r_f32* sv );
			Matrix34 ( const r::math::Matrix33& rot, const r::math::Vector3D& pos );
			//! 単位行列の作成
			void	identity ( void );
		public:
			//! エイミング
			/*!
			*/
			void	aim ( const r::math::Vector3D& position, const r::math::Vector3D& target, const r::math::Vector3D& upvector );
		public:
			//! 行列の合成
			Matrix34 operator * ( const Matrix34 &src ) const;
			const Matrix34 &operator *= ( const Matrix34 &src );
			//! 行列の全成分に引数srcを掛け合わせる
			Matrix34 operator * ( r_f32 src ) const;
			const Matrix34 &operator *= ( r_f32 src );
			//! 行列の加算
			Matrix34 operator + ( const Matrix34 &src ) const;
			const Matrix34 &operator += ( const Matrix34 &src );
			//! 行列の転置(移動値が逆行列化する)
			void	transposeInverse ( void );
			//! 行列の転置(シェーダでdot積で計算する為)
			void	transpose ( Matrix44& dst );
			//! 移動行列の作成
			const Matrix34 &translate ( const r::math::Vector3D &src );
			//! 現在の行列の移動成分のみを設定する
			const Matrix34 &setTranslate ( const r::math::Vector3D &src );
			//! スケール行列の作成
			const Matrix34 &scale ( const r::math::Vector3D &src );
			const Matrix34 &scale ( r_f32 src );
			//! X軸回転の行列を設定
			/*!
			@param	src	[in]	x軸での回転(ラジアン)
			*/
			const Matrix34 &rotateX ( r_f32 src );
			//! Y軸回転の行列を設定
			/*!
			@param	src	[in]	y軸での回転(ラジアン)
			*/
			const Matrix34 &rotateY ( r_f32 src );
			//! Z軸回転の行列を設定
			/*!
			@param	src	[in]	z軸での回転(ラジアン)
			*/
			const Matrix34 &rotateZ ( r_f32 src );
			//! 任意軸での回転行列を設定
			/*!
			@param	vec	[in]	回転軸
			@param	rot	[in]	回転量(ラジアン)
			*/
			const Matrix34 &rotateAxis ( const r::math::Vector3D &vec, r_f32 rot );
			//! 3x3行列成分の抽出
			operator r::math::Matrix33 ( void ) const;
			//! 4x4行列への変換
			operator Matrix44 ( void ) const;
			//! 行列の回転成分のみ設定する
			const Matrix34 &setRotateAxis ( const r::math::Matrix33 &rot );
			//! ベクトルを行列で変換
			r::math::Vector3D	transform3D ( const r::math::Vector2D &vec ) const;
			r::math::Vector3D	transform3D ( const r::math::Vector3D &vec ) const;
			r::math::Vector3D	transform3D33 ( const r::math::Vector3D &vec ) const;
			r::math::Vector4D	transform4D ( const r::math::Vector3D &vec ) const;
			r::math::Vector4D	transform4D ( const r::math::Vector4D &vec ) const;
			//! 行列の各回転成分のスケールを1.0に正規化する
			const Matrix34	&normalize ( void );
			//! 行列のスケールを取得
			r::math::Vector3D getSize ( void ) const;
			//! 構成成分のオイラー角を取得
			r::math::Vector3D	EulerXYZ ( void ) const;
			r::math::Vector3D	EulerXZY ( void ) const;
			r::math::Vector3D	EulerYXZ ( void ) const;
			r::math::Vector3D	EulerYZX ( void ) const;
			r::math::Vector3D	EulerZXY ( void ) const;
			r::math::Vector3D	EulerZYX ( void ) const;
			//! XYZ軸に対してオイラー角3つを指定して回転行列を作成する
			/*! いずれは展開したいです*/
			const Matrix34 &rotateXYZ ( const r::math::Vector3D &rot );
			const Matrix34 &rotateXZY ( const r::math::Vector3D &rot );
			const Matrix34 &rotateYXZ ( const r::math::Vector3D &rot );
			const Matrix34 &rotateYZX ( const r::math::Vector3D &rot );
			const Matrix34 &rotateZXY ( const r::math::Vector3D &rot );
			const Matrix34 &rotateZYX ( const r::math::Vector3D &rot );
		public:
			union {
				struct {
					r_f32		_11;
					r_f32		_12;
					r_f32		_13;
					r_f32		_21;
					r_f32		_22;
					r_f32		_23;
					r_f32		_31;
					r_f32		_32;
					r_f32		_33;
					r_f32		_41;
					r_f32		_42;
					r_f32		_43;
				};
				r_f32			m[4][3];
				r_f32			f[12];
			};
		};
	}
}
#include "../rtti/r_rtti_reflection_typename.h"
namespace r{
	namespace rtti{
		//! r::math::Matrix34
		template<>
		static inline
		const r_cstr	getTypeNameStr<r::math::Matrix34>() {
			return _RST ( "r::math::Matrix34" );
		}
	}
}

#endif // _R_MATH_MATRIX34_H_
